//
//  CLAnimal.m
//  RuntimeTest
//
//  Created by Charles on 16/9/27.
//  Copyright © 2016年 Charles. All rights reserved.
//

#import "CLAnimal.h"

@implementation CLAnimal

/**
 *  第一步：在没有找到方法时，会先调用此方法，可用于动态添加方法
 *  不动态添加
 */
+(BOOL)resolveInstanceMethod:(SEL)sel{
    NSLog(@"------->> %s called",__func__);
    return NO;
}

/**
 *  第二步：上一步返回NO,就会进入这一步，用于指定备选响应此SEL的对象
 *  一定不能返回 self,否则会死循环，自己没有实现这个方法才会进入这一流程，因此成为死循环
 */
- (id)forwardingTargetForSelector:(SEL)aSelector{
    NSLog(@"------->> %s called",__func__);
    return nil;
}

/**
 *  第三步：指定方法签名，若返回nil,则不会进入下一步，而是无法处理消息
 */
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    NSLog(@"------->> %s called",__func__);
    if ([NSStringFromSelector(aSelector) isEqualToString:@"fly"]) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return  [super methodSignatureForSelector:aSelector];
}

/**
 *  当实现了此方法后，-doesNotRecognizeSelector:不会再被调用
 *  如果要测试找不到方法，可以注掉这个方法
 */
- (void)forwardInvocation:(NSInvocation *)anInvocation{
    NSLog(@"------->> %s called",__func__);
    //可以改变选择器
    [anInvocation setSelector:@selector(eat)];
    //改变选择器后，还需要指定是哪个对象的方法
    [anInvocation invokeWithTarget:self];
}

- (void)eat{
    NSLog(@"------->> %s called",__func__);
    NSLog(@"动物都会吃！但是不一定都会飞！！");
}

/**
 *  如果实现fly方法则上面的一系列方法都不会被调用
 */
//- (void)fly{
//    NSLog(@"------->> %s called",__func__);
//}

@end
